package com.acme.bankapp.domain.bank;

import com.acme.bankapp.exceptions.NotEnoughFundsException;
import com.acme.bankapp.exceptions.OverDraftLimitExceededException;

/**
 * This is checking variant of particular implementation of abstract account
 * 
 * @author Anton Kotov
 * 
 */
@SuppressWarnings("serial")
public class CheckingAccount extends AbstractAccount {

    private double overdraft;

    @Override
    public int hashCode() {
	final int prime = 31;
	int result = 1;
	long temp;
	temp = Double.doubleToLongBits(overdraft);
	result = prime * result + (int) (temp ^ (temp >>> 32));
	return result;
    }

    @Override
    public String toString() {
	return super.toString() + " -> CheckingAccount [overdraft=" + overdraft
		+ "]";
    }

    @Override
    public boolean equals(Object obj) {
	if (this == obj) {
	    return true;
	}
	if (obj == null) {
	    return false;
	}
	if (!(obj instanceof CheckingAccount)) {
	    return false;
	}
	CheckingAccount other = (CheckingAccount) obj;
	if (Double.doubleToLongBits(overdraft) != Double
		.doubleToLongBits(other.overdraft)) {
	    return false;
	}
	return true;
    }

    public CheckingAccount(final int id, final double balance,
	    final double overdraft) {
	super(id, balance);

	if (balance + overdraft < 0.) {
	    throw new IllegalArgumentException();
	}

	this.overdraft = overdraft;
    }

    public void withdraw(final double amount)
	    throws OverDraftLimitExceededException {
	if (amount <= 0.) {
	    throw new IllegalArgumentException();
	}
	try {
	    super.withdraw(amount);
	} catch (NotEnoughFundsException e) {
	    throw new OverDraftLimitExceededException(
		    "Failed to withdraw: account is " + this, e);
	}
	assert (balance + overdraft >= 0.) : "balance + overdraft is negative";
    }

    @Override
    public double maximumAmountToWithdraw() {
	return getBalance() + overdraft;
    }
}
